<?php

class Model_ZendDb_AuthService implements Model_AuthService {
	/**
	 * @var Zend_Db
	 */
	private $_db;
	
	/**
	 * @var Zend_Auth
	 */
	private $_auth;
	
	/**
	 * @var array
	 */
	private $_openidProfile;
	
	/**
	 * 
	 * @var Model_ZendDb_DbTable_User
	 */
	private $_user;
    
    public function __construct()
    {
        $this->_auth = Zend_Auth::getInstance();
        $this->_user = new Model_ZendDb_DbTable_User();
        $this->_db = $this->_user->getAdapter();
        $this->_openidProfile = null;
    }
    
    /**
     * Perform User Authentication
     * 
     * @param String $username
     * @param String $password
     * @return boolean
     * @see application/models/Model_AuthService#authenticate($username, $password)
     */
    public function authenticate($username, $password) {
        $isAuthenticated = false;
        
        $authAdapter = new Zend_Auth_Adapter_DbTable($this->_db);
        $authAdapter->setTableName('user')
                    ->setIdentityColumn('username')
                    ->setCredentialColumn('password');
        
        /* 
         * If enabled openid login, password is not set, so the fallbak one is
         * used. Also the 'where' must contain the check against isOpenID = "1"
         */
        $authAdapter->setIdentity($username);        
        if (empty($password)) {        
            $authAdapter->setCredential('none');
                    
            $select = $authAdapter->getDbSelect();

            $select->where('isEnabled = "1" AND isOpenID = "1"');
        } else {
        	/*
        	 * Simple login, check on isOpenID = "0" to prevent using 
        	 * fallback password to force login.
        	 */
            $authAdapter->setCredential($password);
                    
            $select = $authAdapter->getDbSelect();

            $select->where('isEnabled = "1" AND isOpenID = "0"');
        }
        
        $result = $this->_auth->authenticate($authAdapter);
        
        if ($result->isValid()) {	
            $userInfo = $authAdapter->getResultRowObject(null, 'password');
            
            // NOTICE This will catch only ONE role for the selected user
            $userRow = $this->_user->find($userInfo->oid)->current();
            $userRoleRow = $userRow->findManyToManyRowset('Model_ZendDb_DbTable_Role', 'Model_ZendDb_DbTable_UserRoles')->current();
            $userProfileRow = $userRow->findParentRow('Model_ZendDb_DbTable_UserProfile');
            
            $user = new Model_Entity_User($userRow->toArray());
            $userRole = new Model_Entity_Role($userRoleRow->toArray());
            $userProfile = new Model_Entity_UserProfile($userProfileRow->toArray());
            $user->setRoles($userRole);
            $user->setUserProfile($userProfile);
            
            $authStorage = $this->_auth->getStorage();
            $authStorage->write($user);
            
            $this->_user->update(
               array('lastLogin' => date('Y-m-d H:i:s')), 
               array('oid = ?' => $userInfo->oid)
            );
            
            $isAuthenticated = true;
        } else {
        	$this->_auth->clearIdentity();
        }
        
        return $isAuthenticated;
    }
    
    /**
     * Perform User Authentication using openID protocol
     * Retrieve also the user profile if it is available
     * 
     * @param String $username The openID user identifier
     * @param String $returnTo The url openid provider call after authentication
     * @return boolean 
     * @see application/models/Model_UserService#openIDAuth($username)
     */
    public function openIDAuth($username, $returnTo = null)
    {
        $sregProps =  Zend_OpenId_Extension_Sreg::getSregProperties();
        
      	$props = array_fill_keys($sregProps, true);

      	$authAdapter = new Zend_Auth_Adapter_OpenId($username);
        $sreg = new Zend_OpenId_Extension_Sreg($props, null, 1.1);
		
        if ($returnTo !== null) {        
            $authAdapter->setReturnTo($returnTo);
		}
        
		$authAdapter->setExtensions($sreg);
        
        $result = $this->_auth->authenticate($authAdapter);
        
        if ($result->isValid()) {
        	$this->_openidProfile = $sreg->getProperties();
        }
        
        return $result;
    }
    
	/**
     * Get OpenID user profile if it is present and the user is logged in
     * 
     * @return array
	 * @see application/models/Model_AuthService#getOpenIDProfile()
	 */
	public function getOpenIDProfile() {
		return $this->_openidProfile;
	}
    
    /**
     * Perform user logout
     * 
     * @return void
     * @see application/models/Model_UserService#logout()
     */
    public function logout()
    {
        $this->_auth->clearIdentity();
    }

}
